<?php

declare(strict_types=1);
/**
 * This file is part of Hyperf.
 *
 * @link     https://www.hyperf.io
 * @document https://doc.hyperf.io
 * @contact  group@hyperf.io
 * @license  https://github.com/hyperf/hyperf/blob/master/LICENSE
 */
namespace App\Exception\Handler;

use Hyperf\Contract\StdoutLoggerInterface;
use Hyperf\GrpcServer\Exception\Handler\GrpcExceptionHandler;
use Psr\Http\Message\ResponseInterface;
use Throwable;
use App\Utils\ServerUtil;
use Pb\Reply;
use Google\Protobuf\Internal\Message;
use Hyperf\HttpMessage\Stream\SwooleStream;
use Hyperf\Grpc\Parser;
use App\Exception\BusinessException;
use App\Exception\ValidateException;

class ErrorExceptionHandler extends GrpcExceptionHandler
{
    /**
     * @var StdoutLoggerInterface
     */
    protected $logger;

    public function __construct(StdoutLoggerInterface $logger)
    {
        $this->logger = $logger;
    }

    public function handle(Throwable $throwable, ResponseInterface $response)
    {
        $message = new Reply();
        $err = '';
        if ($throwable instanceof BusinessException || $throwable instanceof ValidateException) {
            $err = $throwable->getMessage();
            $err_arr = \explode(\config('web.err_msg_splite'), $err);
            $web_err = $err_arr[0];
            $message->setMsg($web_err);
        } else {
            $err = '网络异常===='.$throwable->getMessage();
            $message->setMsg('网络异常');
        }
        $message->setErrCode(500);
        ServerUtil::info('grpc异常捕获错误日志', ['msg'=>$err,'line'=>$throwable->getLine(),'file'=>$throwable->getFile()]);
        //return $this->transferToResponse($throwable->getCode(), $throwable->getMessage(), $response);
        return $this->handleResponse($message, $response);
    }

    public function isValid(Throwable $throwable): bool
    {
        return true;
    }

    /**
     * Handle GRPC Response.
     * @param int $httpStatus
     */
    protected function handleResponse(?Message $message, ResponseInterface $response, $httpStatus = 200, string $grpcStatus = '0', string $grpcMessage = ''): ResponseInterface
    {
        return $response->withStatus($httpStatus)
            ->withBody(new SwooleStream(Parser::serializeMessage($message)))
            ->withAddedHeader('Server', 'Hyperf')
            ->withAddedHeader('Content-Type', 'application/grpc')
            ->withAddedHeader('trailer', 'grpc-status, grpc-message')
            ->withTrailer('grpc-status', $grpcStatus)
            ->withTrailer('grpc-message', $grpcMessage);
    }
}
